package cn.edu.sgu.www.mhxysy.service.chongwu_equipment.impl;

import cn.edu.sgu.www.mhxysy.consts.CustomMessages;
import cn.edu.sgu.www.mhxysy.dto.chongwu_equipment.ChongwuEquipmentDTO;
import cn.edu.sgu.www.mhxysy.entity.chongwu.Chongwu;
import cn.edu.sgu.www.mhxysy.entity.chongwu_equipment.*;
import cn.edu.sgu.www.mhxysy.entity.xingshi.Xingshi;
import cn.edu.sgu.www.mhxysy.enums.ChongwuEquipmentAttributeTypes;
import cn.edu.sgu.www.mhxysy.enums.InlayStatus;
import cn.edu.sgu.www.mhxysy.enums.WearStatus;
import cn.edu.sgu.www.mhxysy.exception.GlobalException;
import cn.edu.sgu.www.mhxysy.function.computer.score.impl.ChongwuEquipmentScoreComputer;
import cn.edu.sgu.www.mhxysy.mapper.chongwu.ChongwuMapper;
import cn.edu.sgu.www.mhxysy.mapper.chongwu_equipment.*;
import cn.edu.sgu.www.mhxysy.mapper.xingshi.XingshiMapper;
import cn.edu.sgu.www.mhxysy.pager.Pager;
import cn.edu.sgu.www.mhxysy.redis.RedisUtils;
import cn.edu.sgu.www.mhxysy.restful.ResponseCode;
import cn.edu.sgu.www.mhxysy.service.chongwu_equipment.ChongwuEquipmentService;
import cn.edu.sgu.www.mhxysy.util.MathUtils;
import cn.edu.sgu.www.mhxysy.util.ObjectUtils;
import cn.edu.sgu.www.mhxysy.util.StringUtils;
import cn.edu.sgu.www.mhxysy.vo.chongwu_equipment.ChongwuEquipmentVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author 沐雨橙风ιε
 * @version 1.0
 */
@Service
public class ChongwuEquipmentServiceImpl implements ChongwuEquipmentService {

    private final RedisUtils redisUtils;
    private final ChongwuMapper chongwuMapper;
    private final XingshiMapper xingshiMapper;
    private final ChongwuWaiguanMapper chongwuWaiguanMapper;
    private final ChongwuEquipmentMapper chongwuEquipmentMapper;
    private final ChongwuTaozhuangSkillMapper chongwuTaozhuangSkillMapper;
    private final ChongwuWaiguanCategoryMapper chongwuWaiguanCategoryMapper;
    private final ChongwuEquipmentScoreComputer chongwuEquipmentScoreComputer;
    private final ChongwuEquipmentCategoryMapper chongwuEquipmentCategoryMapper;
    private final ChongwuTaozhuangCategoryMapper chongwuTaozhuangCategoryMapper;
    private final ChongwuEquipmentAttributeMapper chongwuEquipmentAttributeMapper;
    private final ChongwuEquipmentViewAttributeMapper chongwuEquipmentViewAttributeMapper;

    @Autowired
    public ChongwuEquipmentServiceImpl(
            RedisUtils redisUtils,
            ChongwuMapper chongwuMapper,
            XingshiMapper xingshiMapper,
            ChongwuWaiguanMapper chongwuWaiguanMapper,
            ChongwuEquipmentMapper chongwuEquipmentMapper,
            ChongwuTaozhuangSkillMapper chongwuTaozhuangSkillMapper,
            ChongwuWaiguanCategoryMapper chongwuWaiguanCategoryMapper,
            ChongwuEquipmentScoreComputer chongwuEquipmentScoreComputer,
            ChongwuEquipmentCategoryMapper chongwuEquipmentCategoryMapper,
            ChongwuTaozhuangCategoryMapper chongwuTaozhuangCategoryMapper,
            ChongwuEquipmentAttributeMapper chongwuEquipmentAttributeMapper,
            ChongwuEquipmentViewAttributeMapper chongwuEquipmentViewAttributeMapper) {
        this.redisUtils = redisUtils;
        this.chongwuMapper = chongwuMapper;
        this.xingshiMapper = xingshiMapper;
        this.chongwuWaiguanMapper = chongwuWaiguanMapper;
        this.chongwuEquipmentMapper = chongwuEquipmentMapper;
        this.chongwuTaozhuangSkillMapper = chongwuTaozhuangSkillMapper;
        this.chongwuWaiguanCategoryMapper = chongwuWaiguanCategoryMapper;
        this.chongwuEquipmentScoreComputer = chongwuEquipmentScoreComputer;
        this.chongwuEquipmentCategoryMapper = chongwuEquipmentCategoryMapper;
        this.chongwuTaozhuangCategoryMapper = chongwuTaozhuangCategoryMapper;
        this.chongwuEquipmentAttributeMapper = chongwuEquipmentAttributeMapper;
        this.chongwuEquipmentViewAttributeMapper = chongwuEquipmentViewAttributeMapper;
    }

    @Override
    public void compute(String equipmentId) {
        UpdateWrapper<ChongwuEquipment> updateWrapper = new UpdateWrapper<>();

        updateWrapper.eq("id", equipmentId);
        updateWrapper.set("score", chongwuEquipmentScoreComputer.compute(equipmentId));

        chongwuEquipmentMapper.update(updateWrapper.getEntity(), updateWrapper);
    }

    @Override
    public void wear(String chongwuId, String equipmentId) {
        // 查询宠物装备信息
        ChongwuEquipment chongwuEquipment = chongwuEquipmentMapper.selectById(equipmentId);

        /*
         * 对比宠物装备的状态
         */
        // 获取宠物装备原来的状态
        int wearStatus = chongwuEquipment.getWearStatus();

        // 宠物装备的状态为0-未穿戴，则操作为穿戴
        if (WearStatus.WCD.getValue().equals(wearStatus)) { // 穿戴
            /*
             * 1、验证宠物装备穿戴的件数限制
             */
            // 查询宠物装备类型
            ChongwuEquipmentCategory chongwuEquipmentCategory = chongwuEquipmentCategoryMapper.selectById(chongwuEquipment.getCategoryId());

            // 构造查询条件
            Map<String, Object > objectMap = new HashMap<>();

            objectMap.put("type", chongwuEquipmentCategory.getType());
            objectMap.put("chongwuId", chongwuId);
            objectMap.put("wearStatus", WearStatus.YCD.getValue());

            int count = chongwuEquipmentMapper.selectSameType(objectMap);

            if (count > 0) {
                throw new GlobalException(ResponseCode.FORBIDDEN, "该宠物已经穿戴了一件相同类型的装备！");
            }

            /*
             * 2、验证宠物装备等级和宠物等级
             */
            // 查询宠物信息
            Chongwu chongwu = chongwuMapper.selectById(chongwuId);

            // 宠物装备的参战等级大于宠物参战等级，抛出异常
            if (chongwuEquipmentCategory.getGrade() > chongwu.getGrade()) {
                throw new GlobalException(ResponseCode.BAD_REQUEST, "装备等级太高了哦");
            }

            /*
             * 3、修改宠物装备信息
             */
            UpdateWrapper<ChongwuEquipment> updateWrapper = new UpdateWrapper<>();

            // where子句
            updateWrapper.eq("id", equipmentId);
            updateWrapper.eq("wear_status", WearStatus.WCD.getValue());

            // set子句
            updateWrapper.set("chongwu_id", chongwuId);
            updateWrapper.set("wear_status", WearStatus.YCD.getValue());

            int update = chongwuEquipmentMapper.update(updateWrapper.getEntity(), updateWrapper);

            if (update == 0) {
                throw new GlobalException(ResponseCode.CONFLICT, "宠物装备的状态更新异常，请刷新页面后重试！");
            }

            /*
             * 4、判断宠物是否激活套装
             */
            Integer taozhuangId = chongwuEquipment.getTaozhuangId();

            // 套装不为空
            if (taozhuangId > 0) {
                Chongwu selectById = chongwuMapper.selectById(chongwuId);

                // 通过宠物类型ID查询宠物套装
                QueryWrapper<ChongwuTaozhuangCategory> queryWrapper1 = new QueryWrapper<>();

                queryWrapper1.eq("chongwu_id", selectById.getCategoryId());

                ChongwuTaozhuangCategory chongwuTaozhuangCategory = chongwuTaozhuangCategoryMapper.selectOne(queryWrapper1);

                if (chongwuTaozhuangCategory != null) {
                    // 查询宠物拥有对应宠物套装的宠物装备列表
                    QueryWrapper<ChongwuEquipment> queryWrapper = new QueryWrapper<>();

                    queryWrapper.ne("taozhuang_id", 0);
                    queryWrapper.eq("wear_status", WearStatus.YCD.getValue());
                    queryWrapper.eq("taozhuang_id", chongwuTaozhuangCategory.getId());

                    List<ChongwuEquipment> list = chongwuEquipmentMapper.selectList(queryWrapper);

                    // 三个套装相同
                    if (list.size() == 3 && taozhuangId.equals(chongwuTaozhuangCategory.getId())) {
                        // 添加宠物的对应套装技能
                        ChongwuTaozhuangSkill chongwuTaozhuangSkill = new ChongwuTaozhuangSkill();

                        chongwuTaozhuangSkill.setId(chongwuTaozhuangSkill.uuid());
                        chongwuTaozhuangSkill.setSkillId(chongwuTaozhuangCategory.getSkillId());
                        chongwuTaozhuangSkill.setChongwuId(chongwuId);

                        chongwuTaozhuangSkillMapper.insert(chongwuTaozhuangSkill);

                        /*
                         * 只要有外观，就一定是对应宠物的外观
                         * 为宠物装备添加对应的外观附加属性
                         */
                        Integer waiguanId = chongwuEquipment.getWaiguanId();

                        // 只要有外观，就一定是对应宠物的外观
                        if (list.size() == 3 && waiguanId > 0) {
                            // 得到宠物装备ID列表
                            Stream<ChongwuEquipment> stream = list.stream();
                            List<String> equipmentIds = stream.map(new Function<ChongwuEquipment, String>() {
                                @Override
                                public String apply(ChongwuEquipment chongwuEquipment) {
                                    return chongwuEquipment.getId();
                                }
                            }).collect(Collectors.toList());

                            equipmentIds.add(chongwuEquipment.getId());

                            // 为宠物装备添加对应的外观附加属性
                            Integer type = ChongwuEquipmentAttributeTypes.WGZJ.getValue();

                            equipmentIds.forEach(new Consumer<String>() {
                                @Override
                                public void accept(String equipmentId) {
                                    // 保存数据到数据库
                                    QueryWrapper<ChongwuEquipmentAttribute> queryWrapper2 = new QueryWrapper<>();

                                    queryWrapper2.eq("equipment_id", chongwuEquipment.getId());
                                    queryWrapper2.eq("type", type);

                                    Long selectCount = chongwuEquipmentAttributeMapper.selectCount(queryWrapper2);

                                    if (selectCount == 0) {
                                        ChongwuWaiguanCategory chongwuWaiguanCategory = chongwuWaiguanCategoryMapper.selectById(waiguanId);

                                        ChongwuEquipmentAttribute equipmentAttribute = new ChongwuEquipmentAttribute();

                                        equipmentAttribute.setId(redisUtils.uuid());
                                        equipmentAttribute.setType(type);
                                        equipmentAttribute.setEquipmentId(equipmentId);
                                        equipmentAttribute.setPropertyId(chongwuWaiguanCategory.getPropertyId());
                                        equipmentAttribute.setPropertyValue(chongwuWaiguanCategory.getPropertyValue());

                                        chongwuEquipmentAttributeMapper.insert(equipmentAttribute);
                                    }
                                }
                            });

                            // 添加宠物外观
                            ChongwuWaiguan chongwuWaiguan = new ChongwuWaiguan();

                            chongwuWaiguan.setId(null);
                            chongwuWaiguan.setChongwuId(chongwuId);
                            chongwuWaiguan.setWaiguanId(waiguanId);

                            chongwuWaiguanMapper.insert(chongwuWaiguan);
                        }
                    }
                }
            }
        } else if (WearStatus.YCD.getValue().equals(wearStatus)) { // 取下
            /*
             * 1、修改宠物装备信息
             */
            UpdateWrapper<ChongwuEquipment> updateWrapper = new UpdateWrapper<>();

            // where子句
            updateWrapper.eq("id", equipmentId);
            updateWrapper.eq("wear_status", WearStatus.YCD.getValue());

            // set子句
            updateWrapper.set("chongwu_id", null);
            updateWrapper.set("wear_status", WearStatus.WCD.getValue());

            int update = chongwuEquipmentMapper.update(updateWrapper.getEntity(), updateWrapper);

            if (update == 0) {
                throw new GlobalException(ResponseCode.CONFLICT, "宠物装备的状态更新异常，请刷新页面后重试！");
            }

            /*
             * 2、删除宠物装备的外观附加属性
             */
            Map<String, Object > columeMap = new HashMap<>();

            columeMap.put("equipment_id", equipmentId);
            columeMap.put("type", 3);

            chongwuEquipmentAttributeMapper.deleteByMap(columeMap);

            /*
             * 3、删除宠物激活的套装效果
             */
            columeMap.clear();
            columeMap.put("chongwu_id", chongwuId);

            chongwuTaozhuangSkillMapper.deleteByMap(columeMap);

            /*
             * 3、删除宠物激活的外观效果
             */
            chongwuWaiguanMapper.deleteByMap(columeMap);
        } else {
            throw new GlobalException(ResponseCode.CONFLICT, "宠物装备状态异常！");
        }
    }

    @Override
    public void insert(ChongwuEquipmentDTO chongwuEquipmentDTO) {
        ChongwuEquipment chongwuEquipment = toEntity(chongwuEquipmentDTO);

        String equipmentId = chongwuEquipment.uuid();

        // 查询宠物装备类型
        ChongwuEquipmentCategory equipmentCategory = chongwuEquipmentCategoryMapper.selectById(
                chongwuEquipment.getCategoryId()
        );

        // 查询一级分类和等级查询预览属性
        QueryWrapper<ChongwuEquipmentViewAttribute> queryWrapper = new QueryWrapper<>();

        queryWrapper.eq("grade", equipmentCategory.getGrade());
        queryWrapper.eq("equipment_id", equipmentCategory.getType());

        List<ChongwuEquipmentViewAttribute> viewAttributes = chongwuEquipmentViewAttributeMapper.selectList(queryWrapper);

        // 得到随机属性类型
        int random = MathUtils.random(0, viewAttributes.size() - 1);
        ChongwuEquipmentViewAttribute chongwuEquipmentViewAttribute = viewAttributes.get(random);
        // 得到随机属性值
        int propertyValue = MathUtils.random(chongwuEquipmentViewAttribute.getMin(), chongwuEquipmentViewAttribute.getMax());

        // 1、添加宠物装备属性
        ChongwuEquipmentAttribute equipmentAttribute = new ChongwuEquipmentAttribute();

        equipmentAttribute.setPropertyValue(propertyValue);
        equipmentAttribute.setId(equipmentAttribute.uuid());
        equipmentAttribute.setEquipmentId(equipmentId);
        equipmentAttribute.setType(ChongwuEquipmentAttributeTypes.JCSX.getValue());
        equipmentAttribute.setPropertyId(chongwuEquipmentViewAttribute.getPropertyId());

        chongwuEquipmentAttributeMapper.insert(equipmentAttribute);

        // 2、添加宠物装备
        chongwuEquipment.setId(equipmentId);
        chongwuEquipment.setChongwuId(null);
        chongwuEquipment.setWearStatus(WearStatus.WCD.getValue());

        chongwuEquipmentMapper.insert(chongwuEquipment);
    }

    @Override
    public void deleteById(String equipmentId) {
        ChongwuEquipment chongwuEquipment = chongwuEquipmentMapper.selectById(equipmentId);
        Integer wearStatus = chongwuEquipment.getWearStatus();
        String chongwuId = chongwuEquipment.getChongwuId();

        // 避免删除还在穿戴中的宠物装备，防止数据不一致
        if (WearStatus.YCD.getValue().equals(wearStatus) || StringUtils.isNotEmpty(chongwuId)) {
            throw new GlobalException(ResponseCode.CONFLICT, "请卸下装备后再删除！");
        }

        // 1、删除宠物装备属性
        Map<String, Object > columnMap = new HashMap<>();

        columnMap.put("equipment_id", equipmentId);

        chongwuEquipmentAttributeMapper.deleteByMap(columnMap);

        // 2、删除宠物装备
        chongwuEquipmentMapper.deleteById(equipmentId);

        // 3、修改星石镶嵌状态
        UpdateWrapper<Xingshi> updateWrapper = new UpdateWrapper<>();

        updateWrapper.eq("equipment_id", equipmentId);

        Long count = xingshiMapper.selectCount(updateWrapper);

        if (count > 0) {
            updateWrapper.clear();
            updateWrapper.set("equipment_id", null);
            updateWrapper.set("inlay_status", InlayStatus.WXQ.getValue());

            xingshiMapper.update(updateWrapper.getEntity(), updateWrapper);
        }
    }

    @Override
    public void updateById(ChongwuEquipmentDTO chongwuEquipmentDTO) {
        String equipmentId = chongwuEquipmentDTO.getId();

        ObjectUtils.requireNonNull(equipmentId, CustomMessages.CHONGWU_EQUIPMENT_ID_NOT_NULL);

        ChongwuEquipment chongwuEquipment = toEntity(chongwuEquipmentDTO);

        chongwuEquipment.setChongwuId(null);
        chongwuEquipment.setWearStatus(WearStatus.WCD.getValue());

        if (chongwuEquipment.getScore() == 0) {
            Integer score = chongwuEquipmentScoreComputer.compute(equipmentId);

            chongwuEquipment.setScore(score);
        }

        chongwuEquipmentMapper.updateById(chongwuEquipment);
    }

    @Override
    public List<ChongwuEquipment> selectAll() {
        return chongwuEquipmentMapper.selectList(null);
    }

    @Override
    public ChongwuEquipment selectById(String id) {
        return chongwuEquipmentMapper.selectById(id);
    }

    @Override
    public Integer getTotalScore(String equipmentId) {
        AtomicInteger totalScore = new AtomicInteger();

        ChongwuEquipment chongwuEquipment = chongwuEquipmentMapper.selectById(equipmentId);

        // 宠物装备评分为0，则计算宠物装备的评分
        Integer score = chongwuEquipment.getScore();

        if (score == 0) {
            score = chongwuEquipmentScoreComputer.compute(equipmentId);
        }

        totalScore.addAndGet(score);

        // 查询宠物装备镶嵌的星石
        QueryWrapper<Xingshi> queryWrapper = new QueryWrapper<>();

        queryWrapper.eq("equipment_id", chongwuEquipment.getId());
        queryWrapper.eq("inlay_status", InlayStatus.YXQ.getValue());

        Xingshi xingshi = xingshiMapper.selectOne(queryWrapper);

        if (xingshi != null) {
            // 星石评分
            totalScore.addAndGet(xingshi.getScore());
        }

        return totalScore.get();
    }

    @Override
    public Page<ChongwuEquipment> selectByPage(Pager<ChongwuEquipment> pager) {
        QueryWrapper<ChongwuEquipment> queryWrapper = Pager.getQueryWrapper(pager, true);
        Page<ChongwuEquipment> page = Pager.ofPage(pager);

        return chongwuEquipmentMapper.selectPage(page, queryWrapper);
    }

    @Override
    public List<ChongwuEquipmentVO> getWeardEquipments(String chongwuId) {
        return chongwuEquipmentMapper.getWeardEquipments(chongwuId);
    }

    @Override
    public List<ChongwuEquipment> selectList(Integer type, String roleId, String chongwuId) {
        if (type == null | roleId == null || chongwuId == null) {
            return new ArrayList<>();
        }

        return chongwuEquipmentMapper.select(type, roleId, chongwuId);
    }

    private ChongwuEquipment toEntity(ChongwuEquipmentDTO chongwuEquipmentDTO) {
        ChongwuEquipment chongwuEquipment = new ChongwuEquipment();

        chongwuEquipment.setId(chongwuEquipmentDTO.getId());
        chongwuEquipment.setScore(chongwuEquipmentDTO.getScore());
        chongwuEquipment.setForger(chongwuEquipmentDTO.getForger());
        chongwuEquipment.setRoleId(chongwuEquipmentDTO.getRoleId());
        chongwuEquipment.setWaiguanId(chongwuEquipmentDTO.getWaiguanId());
        chongwuEquipment.setCategoryId(chongwuEquipmentDTO.getCategoryId());
        chongwuEquipment.setTaozhuangId(chongwuEquipmentDTO.getTaozhuangId());

        return chongwuEquipment;
    }

}